package pl.project.engineering.services;

import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.tapestry5.ioc.annotations.InjectService;
import pl.project.engineering.data.SensorsDto;

/**
 *
 * @author ksmolnicki
 */
@Slf4j
public class SerialReader implements SerialPortEventListener {

  private final Repository repo;
  
  private SerialComPort serialComPort;

  private InputStream inputStream;

  private byte[] buffer = new byte[1024];

  private int idx = 0;

  public SerialReader(@InjectService("Repository") Repository repo) {
    this.repo = repo;
  }
  
  public void setup (SerialComPort serialComPort) throws IOException {
    this.serialComPort = serialComPort;
    this.inputStream = serialComPort.getInputStream();
  }

  @Override
  public void serialEvent(SerialPortEvent spe) {
    try {
      readData();
    } catch (IOException e) {
      log.error("Error while reading from serial port", e);
      serialComPort.disconnect();
    }
  }
  
  private void readData() throws IOException{
      while (inputStream.available() > 0) {
        buffer[idx] = (byte) inputStream.read();
        if (buffer[idx] == '\n') {
          SensorsDto dto = buildSensorsDto(new String(buffer));
          if (dto != null) {
            repo.addMeasurment(dto);
          }
          buffer = new byte[1024];
          idx = 0;
        } else {
          idx++;
        }
      }
  }

  private SensorsDto buildSensorsDto(String valuesFromSerialPort) {
    if (valuesFromSerialPort.startsWith("D>")) {

      Iterable<String> keyValues = Splitter.on(';').trimResults().omitEmptyStrings().split(valuesFromSerialPort);
      Map<String, Double> values = Maps.newHashMap();

      for (String keyValue : keyValues) {
        String[] temp = keyValue.split("=");
        values.put(temp[0], Double.parseDouble(temp[1]));
      }

      Double[] temp = new Double[]{values.get("sht10_temp"),
        values.get("t1"),values.get("t2"),values.get("t3")};

      return new SensorsDto(new Date().getTime(), temp, values.get("sht10_humi"), values.get("sht10_dewp"));
    } else {
      return null;
    }
  }
}
